/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.cjj;

import com.cjj.library.ResourceTable;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.agp.window.service.DisplayManager;
import ohos.app.Context;
import ohos.global.resource.NotExistException;
import ohos.global.resource.ResourceManager;
import ohos.global.resource.WrongTypeException;
import ohos.hiviewdfx.HiLog;

import java.io.IOException;

public class CircleProgressBar extends Component implements MaterialHeadListener, Component.EstimateSizeListener,
        Component.DrawTask, Component.LayoutRefreshedListener {

    private static final int KEY_SHADOW_COLOR = 0x1E000000;
    private static final int FILL_SHADOW_COLOR = 0x3D000000;
    // PX
    private static final float X_OFFSET = 0f;
    private static final float Y_OFFSET = 1.75f;
    private static final float SHADOW_RADIUS = 3.5f;
    private static final int SHADOW_ELEVATION = 4;

    public static final int DEFAULT_CIRCLE_BG_LIGHT = 0xFFFAFAFA;
    private static final int DEFAULT_CIRCLE_DIAMETER = 40;
    private static final int STROKE_WIDTH_LARGE = 3;
    public static final int DEFAULT_TEXT_SIZE = 9;

    private int mBackGroundColor;
    private int mProgressColor;
    private int mProgressStokeWidth;
    private int mArrowWidth = -1;
    private int mArrowHeight = -1;
    private int mProgress;
    private int mMax;
    private int mDiameter;
    private int mInnerRadius;
    private Paint mTextPaint;
    private int mTextColor;
    private int mTextSize;
    private boolean mIfDrawText;
    private boolean mShowArrow;
    public MaterialProgressDrawable mProgressDrawable;
    private ShapeElement mBgCircle;
    private boolean mCircleBackgroundEnabled;
    private int[] mColors = new int[]{Color.BLACK.getValue()};

    public CircleProgressBar(Context context) {
        this(context, null);

    }

    public CircleProgressBar(Context context, AttrSet attrs) {
        this(context, attrs, null);

    }

    public CircleProgressBar(Context context, AttrSet attrs, String defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs);
    }

    private void init(Context context, AttrSet attrs) {
        setEstimateSizeListener(this);
        setLayoutRefreshedListener(this);
        onAttachedToWindow();
        addDrawTask(this);
//        setBindStateChangedListener(new BindStateChangedListener() {
//            @Override
//            public void onComponentBoundToWindow(Component component) {
//                onAttachedToWindow();
//            }
//
//            @Override
//            public void onComponentUnboundFromWindow(Component component) {
//                onDetachedFromWindow();
//            }
//        });
        float density = DisplayManager.getInstance().getDefaultDisplay(context).get().getAttributes().densityPixels;
        if (attrs != null) {
            mBackGroundColor = AttrUtils.getColor(attrs, "mlpb_background_color", DEFAULT_CIRCLE_BG_LIGHT);
            mProgressColor = AttrUtils.getColor(attrs, "mlpb_progress_color", DEFAULT_CIRCLE_BG_LIGHT);
            mColors = new int[]{mProgressColor};
            mInnerRadius = AttrUtils.getInteger(attrs, "mlpb_inner_radius", -1);
            mProgressStokeWidth = AttrUtils.getInteger(attrs, "mlpb_progress_stoke_width", (int) (STROKE_WIDTH_LARGE * density));
            mArrowWidth = AttrUtils.getInteger(attrs, "mlpb_arrow_width", -1);
            mArrowHeight = AttrUtils.getInteger(attrs, "mlpb_arrow_height", -1);
            System.out.println(mArrowWidth + "  aaaaa   " + mArrowHeight);
            mTextSize = AttrUtils.getInteger(attrs, "mlpb_progress_text_size", (int) (DEFAULT_TEXT_SIZE * density));
            mTextColor = AttrUtils.getColor(attrs, "mlpb_progress_text_color", Color.BLACK.getValue());
            mShowArrow = AttrUtils.getBoolean(attrs, "mlpb_show_arrow", false);
            mCircleBackgroundEnabled = AttrUtils.getBoolean(attrs, "mlpb_enable_circle_background", true);
            mProgress = AttrUtils.getInteger(attrs, "mlpb_progress", 0);
            mMax = AttrUtils.getInteger(attrs, "mlpb_max", 100);
            int textVisible = AttrUtils.getInteger(attrs, "mlpb_progress_text_visibility", 1);
            if (textVisible != 1) {
                mIfDrawText = true;
            }
        }
        mTextPaint = new Paint();
        mTextPaint.setStyle(Paint.Style.FILL_STYLE);
        mTextPaint.setColor(new Color(mTextColor));
        mTextPaint.setTextSize(mTextSize);
        mTextPaint.setAntiAlias(true);

        mProgressDrawable = new MaterialProgressDrawable(context, this);
        mProgressDrawable.setCallback(this::invalidate);
        mProgressDrawable.setStartEndTrim(0, (float) 0.75);
//        setImageElement(mProgressDrawable);

//        try {
//            PixelMapElement element = new PixelMapElement(getResourceManager().getResource(ResourceTable.Media_a));
//            setImageElement(element);
//        } catch (IOException | NotExistException e) {
//            e.printStackTrace();
//        }

    }

    public void setProgressBackGroundColor(int color) {
        this.mBackGroundColor = color;
        invalidate();
    }

    public void setTextColor(int color) {
        this.mTextColor = color;
    }

    @Override
    public boolean onEstimateSize(int widthMeasureSpec, int heightMeasureSpec) {
        System.out.println("ddddddddd onEstimateSize");
//        if (!elevationSupported()) {
//        setEstimatedSize(getEstimatedWidth() + mShadowRadius * 2, getEstimatedHeight()
//                + mShadowRadius * 2);
//        }
        return false;
    }

    public int getProgressStokeWidth() {
        return mProgressStokeWidth;
    }

    public void setProgressStokeWidth(int mProgressStokeWidth) {
        final float density = DisplayManager.getInstance().getDefaultDisplay(getContext()).get().getAttributes().densityPixels;
        this.mProgressStokeWidth = (int) (mProgressStokeWidth * density);
        invalidate();
    }

    @Override
    public void arrange(int left, int top, int width, int height) {
//        super.arrange(left, top, width, height);

    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        if (mIfDrawText) {
            String text = String.format("%s%%", mProgress);
            int x = getWidth() / 2 - text.length() * mTextSize / 4;
            int y = getHeight() / 2 + mTextSize / 4;
            canvas.drawText(mTextPaint, text, x, y);
        }
//        System.out.println("ddddddddd onDraw");
//        canvas.drawColor(0xffff0000, BlendMode.SRC);
        mProgressDrawable.setBounds(0, 0, getWidth(), getHeight());
        mProgressDrawable.drawToCanvas(canvas);
    }
//
//    @Override
//    final public void setImageElement(Element element) {
//        super.setImageElement(element);
//    }

    public boolean isShowArrow() {
        return mShowArrow;
    }

    public void setShowArrow(boolean showArrow) {
        this.mShowArrow = showArrow;
        invalidate();
    }

//    public void setAnimationListener(Animator.StateChangedListener listener) {
//        mListener = listener;
//    }
//
//    @Override
//    public void onStart(Animator animator) {
//        if (mListener != null) {
//            mListener.onStart(animator);
//        }
//    }
//
//    @Override
//    public void onStop(Animator animator) {
//
//    }
//
//    @Override
//    public void onCancel(Animator animator) {
//
//    }
//
//    @Override
//    public void onEnd(Animator animator) {
//        if (mListener != null) {
//            mListener.onEnd(animator);
//        }
//    }
//
//    @Override
//    public void onPause(Animator animator) {
//
//    }
//
//    @Override
//    public void onResume(Animator animator) {
//
//    }

    /**
     * Set the color resources used in the progress animation from color resources.
     * The first color will also be the color of the bar that grows in response
     * to a user swipe gesture.
     *
     * @param colorResIds 颜色
     */
    public void setColorSchemeResources(int... colorResIds) {
        final ResourceManager res = getResourceManager();
        int[] colorRes = new int[colorResIds.length];
        for (int i = 0; i < colorResIds.length; i++) {
            try {
                colorRes[i] = res.getElement(colorResIds[i]).getColor();
            } catch (IOException | NotExistException | WrongTypeException e) {
                e.printStackTrace();
            }
        }
        setColorSchemeColors(colorRes);
    }

    /**
     * Set the colors used in the progress animation. The first
     * color will also be the color of the bar that grows in response to a user
     * swipe gesture.
     *
     * @param colors 颜色
     */
    public void setColorSchemeColors(int... colors) {
        mColors = colors;
        if (mProgressDrawable != null) {
            mProgressDrawable.setColorSchemeColors(colors);
        }
    }

    /**
     * Update the background color of the mBgCircle image view.
     *
     * @param colorRes 颜色int值
     */
    public void setBackgroundColor(int colorRes) {
        if (getBackgroundElement() instanceof ShapeElement) {
            final ResourceManager res = getResourceManager();
//            ((ShapeElement) getBackgroundElement()).getPaint().setColor(res.getColor(colorRes));
        }
    }

    public boolean isShowProgressText() {
        return mIfDrawText;
    }

    public void setShowProgressText(boolean mIfDrawText) {
        this.mIfDrawText = mIfDrawText;
    }

    public int getMax() {
        return mMax;
    }

    public void setMax(int max) {
        mMax = max;
    }

    public int getProgress() {
        return mProgress;
    }

    public void setProgress(int progress) {
        if (getMax() > 0) {
            mProgress = progress;
        }
        invalidate();
        HiLog.info(Contants.LABEL, "progress------->>>>" + progress);
    }


    public boolean circleBackgroundEnabled() {
        return mCircleBackgroundEnabled;
    }

    public void setCircleBackgroundEnabled(boolean enableCircleBackground) {
        this.mCircleBackgroundEnabled = enableCircleBackground;
        invalidate();
    }

    @Override
    public int getVisibility() {
        return super.getVisibility();
    }

    @Override
    public void setVisibility(int visibility) {
        super.setVisibility(visibility);
//        if (mProgressDrawable != null) {
//            mProgressDrawable.setVisible(visibility == VISIBLE, false);
//            if (visibility != VISIBLE) {
//                mProgressDrawable.stop();
//            } else {
//                if (mProgressDrawable.isRunning()) {
//                    mProgressDrawable.stop();
//                }
//                mProgressDrawable.start();
//            }
//        }
    }

    protected void onAttachedToWindow() {
        if (mProgressDrawable != null) {
            mProgressDrawable.onStop();
            mProgressDrawable.setVisible(getVisibility() == VISIBLE, false);
        }
    }

    protected void onDetachedFromWindow() {
        if (mProgressDrawable != null) {
            mProgressDrawable.onStop();
            mProgressDrawable.setVisible(false, false);
        }
    }

    @Override
    public void onComlete(MaterialRefreshLayout materialRefreshLayout) {
        if (mProgressDrawable != null) {
            mProgressDrawable.onStop();
        }
        setVisibility(Component.INVISIBLE);
    }

    @Override
    public void onBegin(MaterialRefreshLayout materialRefreshLayout) {
        setVisibility(Component.VISIBLE);
        invalidate();
//        mProgressDrawable.setStartEndTrim(0, (float) 0.75);
    }

    @Override
    public void onPull(MaterialRefreshLayout materialRefreshLayout, float fraction) {
        if (mProgressDrawable != null)
            mProgressDrawable.setProgressRotation(fraction);

        invalidate();
    }

    @Override
    public void onRelease(MaterialRefreshLayout materialRefreshLayout, float fraction) {

    }

    @Override
    public void onRefreshing(MaterialRefreshLayout materialRefreshLayout) {
        if (mProgressDrawable != null) {
            mProgressDrawable.onStart();
        }
    }

    @Override
    public void onRefreshed(Component component) {
        final float density = DisplayManager.getInstance().getDefaultDisplay(getContext()).get().getAttributes().densityPixels;
        mDiameter = Math.min(getEstimatedWidth(), getEstimatedHeight());
        if (mDiameter <= 0) {
            mDiameter = (int) density * DEFAULT_CIRCLE_DIAMETER;
        }
        if (getBackgroundElement() == null && mCircleBackgroundEnabled) {
            mBgCircle = new ShapeElement(getContext(), ResourceTable.Graphic_oval_bg);
            setBackground(mBgCircle);
        }
        mProgressDrawable.setBackgroundColor(mBackGroundColor);
        mProgressDrawable.setColorSchemeColors(mColors);
        mProgressDrawable.setSizeParameters(mDiameter, mDiameter,
                mInnerRadius <= 0 ? (mDiameter - mProgressStokeWidth * 2) / (double) 4 : mInnerRadius,
                mProgressStokeWidth,
                mArrowWidth < 0 ? mProgressStokeWidth * 4 : mArrowWidth,
                mArrowHeight < 0 ? mProgressStokeWidth * 2 : mArrowHeight);
        if (isShowArrow()) {
            mProgressDrawable.showArrowOnFirstStart(true);
            mProgressDrawable.setArrowScale(1f);
            mProgressDrawable.showArrow(true);
        }
//        super.setImageElement(null);
//        super.setImageElement(mProgressDrawable);
        mProgressDrawable.setAlpha(255);
        if (getVisibility() == VISIBLE) {
            mProgressDrawable.setStartEndTrim(0, (float) 0.8);
        }
    }
}
